package org.xx.armory.commons;

import java.util.Date;

/**
 * 时间点范围。
 */
public final class DateRange {
    private static final long MIN_VALUE = 0L;
    /**
     * 3000/01/03 GMT
     */
    private static final long MAX_VALUE = 32503852800000L;

    private final long start;
    private final long end;

    /**
     * 构造时间点范围对象。
     *
     * @param start
     *         起始时间点。
     * @param end
     *         终止时间点。
     * @throws IllegalArgumentException
     *         如果参数{@code start}或者{@code end}小于{@code 0L}，或者参数{@code start}小于{@code end}。
     */
    public DateRange(
            long start,
            long end
    ) {
        if (end < start) {
            throw new IllegalArgumentException("Argument \"start\" should greater than or equal to \"end\", but " + new Date(start) + " and " + new Date(end));
        }

        this.start = start;
        this.end = end;
    }

    /**
     * 构造时间点范围对象。
     *
     * @param start
     *         起始时间点，如果此参数是{@code null}则取默认起始时间。
     * @param end
     *         终止时间点，如果此参数是{@code null}则取默认终止时间。
     * @throws IllegalArgumentException
     *         如果参数{@code start}小于{@code end}。
     */
    public DateRange(
            Date start,
            Date end
    ) {
        final long start_ = start != null ? start.getTime() : MIN_VALUE;
        final long end_ = end != null ? end.getTime() : MAX_VALUE;

        if (end_ < start_) {
            throw new IllegalArgumentException("Argument \"start\" should greater than or equal to \"end\", but " + new Date(start_) + " and " + new Date(end_));
        }

        this.start = start_;
        this.end = end_;
    }

    /**
     * 获取此范围的起始时间点。
     *
     * @return 此范围的起始时间点。
     */
    public Date getStart() {
        return new Date(this.start);
    }

    /**
     * 获取此范围的结束时间点。
     *
     * @return 此范围的结束时间点。
     */
    public Date getEnd() {
        return new Date(this.end);
    }

    @Override
    public int hashCode() {
        return (int) (31 * start + end);
    }

    @Override
    public boolean equals(
            Object other
    ) {
        if (this == other) return true;
        if (other == null || getClass() != other.getClass()) return false;
        DateRange dateRange = (DateRange) other;
        return start == dateRange.start && end == dateRange.end;
    }

    @Override
    public String toString() {
        return "(" + getStart() + "," + getEnd() + ")";
    }
}
